using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

public static class Extensions
{
    private static readonly XmlSerializerNamespaces defaultNamespace;

    static Extensions()
    {
        // 使用此命名空间，生成干净的xml
        defaultNamespace = new XmlSerializerNamespaces();
        defaultNamespace.Add("", "");
    }

    /// <summary>
    /// 将对象转化为xml
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="obj"></param>
    /// <param name="namespaceName"></param>
    /// <returns></returns>
    public static string ToXml<T>(this T obj, bool isDeleteHeader = false)
    {
        using (var sw = new StringWriterWithEncoding(Encoding.UTF8))
        {
            var serializer = new XmlSerializer(typeof(T));
            serializer.Serialize(sw, obj, defaultNamespace);
            var xml = sw.ToString();
            if (isDeleteHeader) // 去掉xml的头部
            {
                xml = Regex.Replace(xml, @"<\?xml.+\?>", "").Trim();
            }
            return xml;
        }
    }

    /// <summary>
    /// 将对象转化为xml
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="obj"></param>
    /// <param name="namespaceName"></param>
    /// <returns></returns>
    public static string ToXml2<T>(this T obj)
    {
        if (obj == null)
            return "";
        using (var sw = new StringWriterWithEncoding(Encoding.UTF8))
        {
            var serializer = new XmlSerializer(typeof(T));
            serializer.Serialize(sw, obj, defaultNamespace);
            var xml = sw.ToString();
            // 去掉xml的头部
            xml = Regex.Replace(xml, @"<\?xml.+\?>", "").Trim();
            // 加上通用的头部
            xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + Environment.NewLine + xml;
            return xml;
        }
    }

    
        /// <summary>
        /// 将xml转化为JObject
        /// </summary>
        /// <param name="xml"></param>
        /// <returns></returns>
        public static JObject ToJObject(this string xml)
        {
            xml = Regex.Replace(xml, @"<\?xml.+\?>", "").Trim();
            var doc = new XmlDocument();
            doc.LoadXml(xml);
            var json = JObject.Parse(JsonConvert.SerializeXmlNode(doc));
            return json;
        }

        /// <summary>
        /// 获取节点内容
        /// </summary>
        /// <param name="json"></param>
        /// <param name="path"></param>
        /// <param name="id"></param>
        /// <returns></returns>
        public static string GetNodeContent(this JObject json, string path, string id = null)
        {
            var element = json.SelectToken(path);
            if (element == null) return "";
            if (id == null)
            {
                if (element is JArray) element.ToList().First().Value<string>();
                return element.Value<string>();
            }
            // 此节点为数组，需要根据id获取指定的元素
            var arr = id.Split('|');
            var field = arr[0];
            var idValue = arr[1];
            var retValue = arr[2];
            // 在数组中查询指定id的节点
            return element.ToList().FirstOrDefault(item => item.Value<string>(field) == idValue)?
                .Value<string>(retValue);
        }
}

/// <summary>
/// 格式化xml时，可设置encoding的类
/// </summary>
public sealed class StringWriterWithEncoding : StringWriter
{
    private readonly Encoding encoding;

    public StringWriterWithEncoding(Encoding encoding)
    {
        this.encoding = encoding;
    }

    public override Encoding Encoding
    {
        get => encoding;
    }
}
